package zcj.stu.C47;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;

import java.util.Optional;

@Configuration
public class C47 {
    public static void main(String[] args) throws Exception{
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(C47.class);
        DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
        //1.根据成员变量的类型注入
        DependencyDescriptor dd1 = new DependencyDescriptor(Bean1.class.getDeclaredField("bean2"), false);
        Bean2 bean2 =(Bean2) beanFactory.doResolveDependency(dd1, "bean1", null, null);
        System.out.println(bean2);
        //根据方法参数注入
        DependencyDescriptor dd2=new DependencyDescriptor(new MethodParameter(Bean1.class.getMethod("setBean2", Bean2.class),0),false);
        Object bean22 = beanFactory.doResolveDependency(dd2, "bean1", null, null);
        System.out.println(bean22);
        //包装类的注入
        DependencyDescriptor dd3 = new DependencyDescriptor(Bean1.class.getDeclaredField("oBean2"), false);
        System.out.println(dd3.getDependencyType());
        if(dd3.getDependencyType()==Optional.class){
            dd3.increaseNestingLevel();
            Object result = beanFactory.doResolveDependency(dd3, "bean1", null, null);
            Optional<Object> bean222 = Optional.ofNullable(result);
            System.out.println(bean222);
        }
        //工厂类的注入
        DependencyDescriptor dd4 = new DependencyDescriptor(Bean1.class.getDeclaredField("ofBean2"), false);
        System.out.println(dd4.getDependencyType());
        if(dd4.getDependencyType()==ObjectFactory.class){
            dd4.increaseNestingLevel();
            ObjectFactory<Object> bean222Factory = () -> beanFactory.doResolveDependency(dd4, "bean1", null, null);
            System.out.println(bean222Factory.getObject());
        }
        //加了@Lazy的bean的注入
        DependencyDescriptor dd5 = new DependencyDescriptor(Bean1.class.getDeclaredField("pBean2"), false);
        ContextAnnotationAutowireCandidateResolver resolver=new ContextAnnotationAutowireCandidateResolver();
        resolver.setBeanFactory(beanFactory);
        Object proxy = resolver.getLazyResolutionProxyIfNecessary(dd5, "bean1");
        System.out.println(proxy);
        System.out.println(proxy.getClass());
    }
    static class Bean1{
        @Autowired
        private Bean2 bean2;
        @Autowired
        public void setBean2(Bean2 bean2){
            this.bean2=bean2;
        }
        @Autowired
        private Optional<Bean2>oBean2;
        @Autowired
        private ObjectFactory<Bean2>ofBean2;
        @Autowired @Lazy
        private Bean2 pBean2;
    }
    @Component
    static class Bean2{
    }
}
